package edu.geektime.jiangfan.chaptrt04;

import java.util.Date;
import java.util.Random;
import java.util.concurrent.*;

/**
 *
 */
public class ThreadCount {
    public static void main(String[] args) {
        //  ThreadCount.futureTaskAndCallableImpl();
        //   ThreadCount.threadPoolCallableImpl();
       // ThreadCount.forkJoinImpl();
      //  ThreadCount.completableFutureImpl();

    }

    // 第一种实现方式
    static void futureTaskAndCallableImpl() {
        FutureTask futureTask = new FutureTask(() -> {
            return "futureTaskAndCallableImpl() 返回的结果:" + new Date();
        });
        new Thread(futureTask).start();

        try {
            System.out.println("執行結果====>" + futureTask.get(1, TimeUnit.MINUTES));
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            System.exit(-1);
        }

    }

    // 第二种实现方式
    static void threadPoolCallableImpl() {
        ExecutorService executorService = Executors.newCachedThreadPool();
        Future<String> future = executorService.submit(() -> {
            return "threadPoolCallableImpl() 返回的結果:" + new Date();
        });
        try {
            System.out.println(future.get(1, TimeUnit.MINUTES));
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            executorService.shutdown();
            if (!executorService.isShutdown()) {
                executorService.shutdownNow();
            }
        }
    }


    // 第三种实现方式
    static void forkJoinImpl() {
        long[] array = new long[2000];
        long expectedSum = 0;
        for (int i = 0; i < array.length; i++) {
            array[i] = random();
            expectedSum += array[i];
        }
        System.out.println("Expected sum: " + expectedSum);
        // fork/join:
        ForkJoinTask<Long> task = new RecursiveTaskSon(array, 0, array.length);
        long startTime = System.currentTimeMillis();
        Long result = ForkJoinPool.commonPool().invoke(task);
        long endTime = System.currentTimeMillis();
        System.out.println("Fork/join sum: " + result + " in " + (endTime - startTime) + " ms.");
    }

    static void completableFutureImpl() {
        try {
            String s = CompletableFuture.supplyAsync(() -> {
                return "返回一個結果:" + new Date();
            }).get();
            System.out.println(s);
        } catch (Exception e) {
           e.printStackTrace();
        }

    }

    static Random random = new Random(0);

    static long random() {
        return random.nextInt(10000);
    }

    static class RecursiveTaskSon extends RecursiveTask<Long> {
        static final int THRESHOLD = 500;
        long[] array;
        int start;
        int end;

        RecursiveTaskSon(long[] array, int start, int end) {
            this.array = array;
            this.start = start;
            this.end = end;
        }

        @Override
        protected Long compute() {
            if (end - start <= THRESHOLD) {
                // 如果任务足够小,直接计算:
                long sum = 0;
                for (int i = start; i < end; i++) {
                    sum += this.array[i];
                    // 故意放慢计算速度:
                    try {
                        Thread.sleep(1);
                    } catch (InterruptedException e) {
                    }
                }
                return sum;
            }
            // 任务太大,一分为二:
            int middle = (end + start) / 2;
            System.out.println(String.format("split %d~%d ==> %d~%d, %d~%d", start, end, start, middle, middle, end));
            RecursiveTaskSon subtask1 = new RecursiveTaskSon(this.array, start, middle);
            RecursiveTaskSon subtask2 = new RecursiveTaskSon(this.array, middle, end);
            invokeAll(subtask1, subtask2);
            Long subresult1 = subtask1.join();
            Long subresult2 = subtask2.join();
            Long result = subresult1 + subresult2;
            System.out.println("result = " + subresult1 + " + " + subresult2 + " ==> " + result);
            return result;
        }
    }
}
